class Cardioid extends WallMode {
  PImage points = createImage(48, 48, RGB);
  int sqsz = 480;
  int dotsize = sqsz/(48)+1;
  // int bright = 256;
  // int zagrate = 24;
 
  Cardioid() {
    background(0); 
    frameRate(60);
    points.updatePixels();
    //random();
    colorMode(RGB, 255);
  }
 
//  colorMode(RGB, 255);
  
  int getDisplayTime() {
    return 10;
  }



  // infrastructure for complex numbers


  public class complex {
    public float re = 0;
    public float im = 0;
    // here's the constructor
    public complex(float a, float b)
    {
      this.re = a;
      this.im = b;
    }



    public complex cadd(complex u, complex v)
    {
      return new complex(u.re + v.re, u.im+v.im);
    }

    public complex cmult(complex u, complex v)
    {
      float rprod = (u.re*v.re - u.im*v.im);
      float cprod = (u.re*v.im + u.im*v.re);
      return new complex(rprod, cprod);
    }
    public complex sqr(complex a)
    {
      return cmult(a, a);
    }

    public complex cbr(complex a)
    {
      return cmult(a, cmult(a, a));
    }
  }



  public float norm(complex a)
  {
    return sqrt(a.re*a.re + a.im*a.im);
  }



  //Okay, that takes care of the infrastructure of complex numbers, more or less
  //The next thing to do is to write an hsv2rgb function, and it's best to do it
  //in full generality so I can play around with the s and v later. 

  public color hsv2rgb(float hue, float saturation, float value)
  {
    float qred;
    float qgreen;
    float qblue;
    int xred=0;
    int xgreen=0; 
    int xblue=0;
    int lexen;
    float nexel;
    float M;
    float N;
    float K;
    if (saturation == 0)
    {
      // achromatic case
      xred = (int) (255.0 * value);
      xgreen = (int) (255.0 * value);
      xblue = (int) (255.0 * value);
    }
    else
    {
      if (hue >= 1.0) {
        hue = 0.0;
      }
      else
      {
        hue = hue * 6;
      }

      lexen = ((int) (hue));
      nexel = hue - ((float) (lexen));

      M = value * (1 - saturation);
      N = value * (1 - saturation * nexel);
      K = value * (1-saturation*(1-nexel));    
      if (lexen==0) { 
        xred = (int) (255.0*value); 
        xgreen = (int) (255.0*K); 
        xblue = (int) (255.0*M);
      } 
      if (lexen==1) { 
        xred = (int) (255.0*N); 
        xgreen = (int) (255.0*value); 
        xblue = (int) (255.0*M);
      } 
      if (lexen==2) { 
        xred = (int) (255.0*M); 
        xgreen = (int) (255.0*value); 
        xblue = (int) (255.0*K);
      } 
      if (lexen==3) { 
        xred = (int) (255.0*M); 
        xgreen = (int) (255.0*N); 
        xblue = (int) (255.0*value);
      } 
      if (lexen==4) { 
        xred = (int) (255.0*K); 
        xgreen = (int) (255.0*M); 
        xblue = (int) (255.0*value);
      } 
      if (lexen==5) { 
        xred = (int) (255.0*value); 
        xgreen = (int) (255.0*M); 
        xblue = (int) (255.0*N);
      }
    }

    return color(xred, xgreen, xblue);
  }

  public color argcolor(complex q)
  {
    return hsv2rgb(atan(q.im/q.re), 1.0, 1.0);
  }



  //Use the Cktalk class to talk to the wall.
  Cktalk wall = new Cktalk();

  int[][] Arr = new int[48][48];
  int[][] Gee = new int[48][48];
  int[][] Bee = new int[48][48];


  // need something a little bit cleverer than three
  // color arrays
  color[][] ledwall = new color[48][48];

  void white()
  {
    for (int x = 0; x < 48 ; x++)
    {
      for (int y = 0 ; y < 48 ; y++)
      {
        ledwall[x][y]=color(255, 255, 255);
      }
    }
  }

  void random() {
    for (int x = 0; x < 48 ; x++)
    {
      for (int y = 0 ; y < 48 ; y++)
      {
        Arr[x][y]=x;
        Gee[x][y]=x;
        Bee[x][y]=y;
      }
    }
  }




  color red = color(255, 0, 0);
  color green = color(0, 255, 0);
  color blue = color(0, 0, 255);
  color cyan = color(0, 255, 255);
  color magenta = color(255, 0, 255);
  color yellow = color(255, 255, 0);
  color black = color(0, 0, 0);




  float X, Y, Z, aX, aY, aZ, R, S, T;
  float U, V, W;
  int t=0;


  // parameters for lorenz
  float rho = 28.0;
  float sigma = 10.0;
  float beta = 8.0/3.0;

  float kel, u;
  int mar, ram, mal;

  complex origin = new complex(0.0, 0.0);
  complex current =origin;

  float xtent, ytent;
  int iter, i;
  complex konstant;
  void mandelbrot()
  {
    konstant = new complex(cos(3.14159*(float)(t)/256.0), sin(3.14159*(float)(t)/256.0));
    for (int x = 0; x < 48 ; x++)
    {

      for (int y = 0; y < 48; y++)
      {
        current = origin;
        xtent = (((float) (x)) - 24.0)/12.0;
        ytent = (((float) (y)) - 24.0)/12.0;
        current = new complex(xtent, ytent);
        for (i=1;i<6;i++)
        {
          current = current.cadd(current.sqr(current), konstant);
        }   
        ledwall[x][y] = argcolor(current);
      }
    }
  }

  void cycle2 (PImage foo) {
    foo.loadPixels();   
    int remain;
    foo.set(24, 24, color(255, 255, 255)); 
    for (int x=0; x <= 47 ; x++)
    {  
      for (int y= 0; y <=47 ; y++)
      {
        foo.set(x, y, ledwall[x][y]);
      }
    }
    foo.updatePixels();
  }



  void draw() {
    t = t + 1;
    mandelbrot();
    //run the cycle2 function on the array of points
    cycle2(points);

    //and let's send it to the wall too

    image(points, 0, 0);
  }

  void keyPressed() {
  }
  void setup() {
  } 
  void modeSelected () {
  }
  int getNewModeIdentifier() { 
    return 1;
  }
}

